import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_widget_from_html_core/flutter_widget_from_html_core.dart';
import 'package:get/get.dart';
import 'package:ichinesereader/exam/dto/assessment.response.dart';
import 'package:ichinesereader/exam/util/ExamUtil.dart';
import 'package:ichinesereader/exam/widgets/BGExamWidget.dart';
import 'package:ichinesereader/exam/widgets/SampleAudioPlayer.dart';
import 'package:ichinesereader/models/assessment/assessmentRecordsGradesResult.dart';
import 'package:ichinesereader/themes/appTheme.dart';
import 'package:ichinesereader/utils/StrUtil.dart';
import 'package:intl/intl.dart';
import 'TeacherRunningRecordController.dart';
import 'TeacherRunningRecordStepper.dart';

class TeacherRunningRecordPage extends GetView<TeacherRunningRecordController> {
  TeacherRunningRecordPage(
      {required this.assessmentId,
      required this.questionRecordId,
      required this.studentName,
      Key? key})
      : super(key: key);
  static const String routeName = '/reports/runningRecord';
  final String assessmentId;
  final String questionRecordId;
  final String studentName;
  final Color blackTextColor = Get.isDarkMode ? Colors.white54 : Colors.black;
  final Color whiteTextColor = Get.isDarkMode ? Colors.black54 : Colors.white;
  @override
  Widget build(BuildContext context) {
    MediaQuery.of(context).size.width;
    if (StrUtil.hasValue(assessmentId) && controller.stepTop.value == -1) {
      controller.getAssessmentByStudentName(
          assessmentId, studentName, questionRecordId);
    }
    return Scaffold(
        body: Padding(
            padding: EdgeInsets.only(top: GetPlatform.isWeb ?10:25),
            child: Stack(children: [
              Obx(() {
                return _buildRunningRecordPage(
                    context, controller.stepTop.value);
              }),
              Positioned(
                  right: 20,
                  child: FloatingActionButton(
                      onPressed: () {
                        Get.back();
                      },
                      backgroundColor: Theme.of(context).colorScheme.secondary,
                      child: const Icon(Icons.close_rounded),
                      tooltip: 'Close'))
            ])));
  }

  Widget _buildRunningRecordPage(BuildContext context, int stepNum) {
    return Container(
        width: double.infinity,
        color: Get.isDarkMode ? AppTheme.colors.darkTheme2 : Colors.white,
        margin: EdgeInsets.fromLTRB(20, GetPlatform.isIOS ? 0 : 20, 20, 10),
        child: _buildMainWidget(context, stepNum));
  }

  Widget _buildMainWidget(BuildContext context, int stepNum) {
    // 0:首页  1:Part2 录音题 2:Part3 选择题 3:Part3 Review 4:AnalysisPage 隐藏掉Stepper
    if (stepNum > -1) {
      ExamRunningRecord? item = controller.recordsGrades!;
      const Color headGreenTextColor = Color(0xff59A59A);

      const StrutStyle strutStyle = StrutStyle(
        forceStrutHeight: true,
        leading: 0.5,
      );

      return Padding(
          padding: EdgeInsets.only(left: 20, right: 20),
          child: Column(children: [
            Column(
              children: [
                Row(crossAxisAlignment: CrossAxisAlignment.end, children: [
                  Text(item.className ?? '',
                      style: TextStyle(
                          color: headGreenTextColor,
                          fontSize: 26,
                          fontWeight: FontWeight.w600,
                          letterSpacing: -0.8)),
                  Text('(${item.classId})',
                      style: TextStyle(
                          color: headGreenTextColor,
                          fontSize: 14,
                          letterSpacing: -0.5)),
                  Text(' / running records for ',
                      style: TextStyle(
                          color: blackTextColor,
                          fontSize: 14,
                          letterSpacing: -0.5)),
                  Text(item.studentName ?? '',
                      style: TextStyle(
                          color: headGreenTextColor,
                          fontSize: 16,
                          letterSpacing: -0.5))
                ]),
                Container(
                    margin: EdgeInsets.fromLTRB(70, 20, 70, 10),
                    padding: EdgeInsets.fromLTRB(20, 7, 20, 7),
                    color: Get.isDarkMode ? Colors.white10 : Color(0x0D000000),
                    child: Row(children: [
                      Text('Title: ',
                          strutStyle: strutStyle,
                          style: TextStyle(
                              color: blackTextColor,
                              fontSize: 16,
                              fontWeight: FontWeight.w700)),
                      Text('${item.title} | ',
                          strutStyle: strutStyle,
                          style: TextStyle(
                              color: blackTextColor,
                              fontSize: 16,
                              letterSpacing: -0.5)),
                      Text('Recorded: ',
                          strutStyle: strutStyle,
                          style: TextStyle(
                              color: blackTextColor,
                              fontSize: 16,
                              fontWeight: FontWeight.w700)),
                      Text(
                          DateFormat('MM/dd/yyyy').format(
                              DateTime.fromMillisecondsSinceEpoch(
                                  item.commitTime!)),
                          strutStyle: strutStyle,
                          style: TextStyle(
                              color: blackTextColor,
                              fontSize: 16,
                              fontWeight: FontWeight.w500))
                    ])),
                Visibility(
                    visible: stepNum < 4,
                    child: TeacherRunningRecordStepper(
                        currentIndex: stepNum > 2 ? 2 : stepNum)),
                Visibility(
                    visible: stepNum == 3,
                    child: Padding(
                        padding: EdgeInsets.only(bottom: 10),
                        child: Text('Reading Result Review',
                            style: TextStyle(
                                fontSize: 22,
                                color: blackTextColor,
                                fontWeight: FontWeight.bold)))),
                Visibility(
                    visible: stepNum == 4,
                    child: Padding(
                        padding: EdgeInsets.only(bottom: 10),
                        child: Text(
                            'Error Analysis/Student\'s Reading Behavior',
                            style: TextStyle(
                                fontSize: 22,
                                color: blackTextColor,
                                fontWeight: FontWeight.bold))))
              ],
            ),
            Expanded(
                child: Container(
                    width: double.infinity,
                    child: Padding(
                        padding: EdgeInsets.all(15),
                        child: AnimatedSwitcher(
                            transitionBuilder: (child, animation) {
                              var tween = Tween<Offset>(
                                  begin: Offset(1, 0), end: Offset(0, 0));
                              return PlaceSlideTransition(
                                  child: child,
                                  position: tween.animate(animation));
                            },
                            duration: Duration(milliseconds: 300),
                            child: _buildGradeWidget(context, stepNum))),
                    decoration: BoxDecoration(
                        border: Border.all(
                          color: Get.isDarkMode
                              ? AppTheme.colors.darkTheme2
                              : Color(0xffDEE2E6),
                          width: 1,
                        ),
                        color:
                            Get.isDarkMode ? Colors.white10 : Color(0xFFF8F9FA),
                        boxShadow: [
                          BoxShadow(
                            blurRadius: 4,
                            spreadRadius: 4,
                            offset: Offset(0, 6),
                            color: Colors.black.withOpacity(0.1),
                          ),
                        ]))),
            SizedBox(height: 10),
            Padding(
              padding: const EdgeInsets.symmetric(vertical: 16.0),
              child: Obx(() => Row(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      if (controller.stepTop.value != -1)
                        ElevatedButton(
                            style: ElevatedButton.styleFrom(
                              textStyle: TextStyle(
                                  fontSize: 20,
                                  fontFamily: 'Montserrat',
                                  letterSpacing: 0.2,
                                  fontWeight: FontWeight.bold),
                              padding: EdgeInsets.symmetric(
                                  horizontal: 42,
                                  vertical: GetPlatform.isWeb ? 20 : 12),
                              backgroundColor: stepNum == 0
                                  ? Get.isDarkMode
                                      ? Colors.white10
                                      : Color(0xFFDEDEDE)
                                  : Get.isDarkMode
                                      ? Colors.white54
                                      : Color(0xFF35A95D),
                              foregroundColor:
                                  stepNum == 0 ? Colors.black45 : Colors.white,
                              shape: RoundedRectangleBorder(
                                borderRadius: BorderRadius.circular(8),
                              ),
                              elevation: 10,
                            ),
                            onPressed: () {
                              if (stepNum == 0) {
                                Get.back();
                              } else {
                                controller.prevPage();
                              }
                            },
                            child: Text((stepNum == 1 || stepNum == 2)
                                ? 'PREV'
                                : 'BACK')),
                      ElevatedButton(
                          style: ElevatedButton.styleFrom(
                            textStyle: TextStyle(
                                fontSize: 20,
                                fontFamily: 'Montserrat',
                                letterSpacing: 0.2,
                                fontWeight: FontWeight.bold),
                            padding: EdgeInsets.symmetric(
                                horizontal: 42,
                                vertical: GetPlatform.isWeb ? 20 : 12),
                            backgroundColor: controller.isNextEnable.value
                                ? Get.isDarkMode
                                    ? Colors.white54
                                    : Color(0xFF35A95D)
                                : Get.isDarkMode
                                    ? Colors.white10
                                    : Color(0x6635A95D),
                            foregroundColor: whiteTextColor,
                            shape: RoundedRectangleBorder(
                              borderRadius: BorderRadius.circular(8),
                            ),
                            elevation: 15,
                          ),
                          onPressed: () {
                            if (stepNum < 5 && controller.isNextEnable.value) {
                              controller.submitPageData();
                            }
                          },
                          child: Text(stepNum > 2 ? 'DONE' : 'NEXT'))
                    ],
                  )),
            )
          ]));
    }
    return Container(
      height: 500,
      color: Colors.transparent,
    );
  }

  Widget _buildPageOne(BuildContext context) {
    // double padding = MediaQuery.of(context).size.width * 0.05;
    double padding = 10;
    List? answer =
        controller.assessmentResult!.list![0].questions![0].question![0].answer;
    String audioId = '';
    if (answer != null && answer.isNotEmpty) {
      audioId = answer[0];
    }
    List<Widget> bottomScoreOptions = [];
    bottomScoreOptions.add(Text('Fluency Score',
        style: TextStyle(
            color: blackTextColor, fontSize: 18, fontWeight: FontWeight.w700)));
    bottomScoreOptions.add(_buildAlertIconButton('partOne'));
    for (int i = 1; i < 5; i++) {
      bottomScoreOptions.add(Obx(() => Row(children: [
            Radio<int>(
                value: i,
                activeColor: Colors.blue,
                groupValue: controller.fluencyScore.value,
                onChanged: (value) {
                  if (controller.isCompleted) return;
                  controller.fluencyScore.value = i;
                  controller.isNextEnable.value = true;
                }),
            Text(i.toString(),
                style: TextStyle(
                    fontFamily: 'Noto Sans SC',
                    fontSize: 18,
                    height: 1.8,
                    color: i == controller.fluencyScore.value
                        ? Colors.blue
                        : (Get.isDarkMode ? Color(0xFF757575) : Colors.black87),
                    fontWeight: FontWeight.w500)),
          ])));
    }

    return Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
      Expanded(
          flex: 7,
          child: Container(
              color: whiteTextColor,
              child: Column(children: [
                Visibility(
                    visible: audioId.isNotEmpty,
                    child: Padding(
                        padding: EdgeInsets.only(bottom: 20,top: 10),
                        child: SampleAudioPlayer(
                          name: 'audioPlayerEvaluation',
                          audioId: audioId,
                          audioUrl: '',
                        ))),
                Expanded(
                    child: Container(
                        width: double.infinity,
                        margin: EdgeInsets.only(left: padding, right: padding),
                        decoration: BoxDecoration(
                            border: Border.all(
                              color: Color(0xffDEE2E6),
                              width: 1,
                            ),
                            borderRadius: BorderRadius.circular(5),
                            color: whiteTextColor),
                        child: Scrollbar(
                          child: SingleChildScrollView(
                            primary: true,
                            child: Padding(
                                padding: EdgeInsets.all(20),
                                child: Column(
                                    crossAxisAlignment:
                                        CrossAxisAlignment.start,
                                    children: _buildArticleContent(context))),
                          ),
                        ))),
                Padding(
                    padding: EdgeInsets.only(left: padding, top: 10),
                    child: Row(children: bottomScoreOptions))
              ]))),
      Expanded(
          flex: 4,
          child: Container(
              color: Get.isDarkMode ? Colors.white10 : Colors.white,
              margin: EdgeInsets.only(bottom: 30),
              child: Obx(() {
                return Scrollbar(
                    child: SingleChildScrollView(
                  primary: true,
                  child: Column(
                      children: controller.scoreList
                          .map(_buildGridTextWidget)
                          .toList()),
                ));
              })))
    ]);
  }

  Widget _buildPageTwo(BuildContext context) {
    List<Widget> options = [];
    QuestionPart? part = controller.assessmentResult?.list![1];
    for (var item in part!.questions!) {
      options.add(_buildRecordTypeItem(context, item.question![0], item.id!));
    }

    String article = controller.articleStr;

    return Scrollbar(
        child: SingleChildScrollView(
            primary: true,
            child: Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
              Expanded(
                  flex: 5,
                  child: Container(
                      padding: EdgeInsets.only(left: 10),
                      child: Column(children: options))),
              Expanded(
                  flex: 3,
                  child: Container(
                      margin: EdgeInsets.only(left: 10),
                      padding: EdgeInsets.all(10),
                      constraints: BoxConstraints(maxHeight: 700),
                      decoration: BoxDecoration(
                          border: Border.all(
                            color: Colors.grey.withOpacity(0.1),
                            width: 1,
                          ),
                          color: Get.isDarkMode
                              ? AppTheme.colors.darkTheme2
                              : Colors.white,
                          boxShadow: [
                            BoxShadow(
                              blurRadius: 6,
                              spreadRadius: 0.2,
                              color: Colors.black.withOpacity(0.1),
                            ),
                          ]),
                      child: SingleChildScrollView(
                        child: HtmlWidget(article,
                            textStyle: TextStyle(
                                fontSize: 16,
                                color: (Get.isDarkMode
                                    ? Color(0xFF757575)
                                    : Colors.black87),
                                height: 1.8)),
                      )))
            ])));
  }

  Widget _buildPageThree(BuildContext context) {
    List<Widget> options = [];
    QuestionPart? part = controller.assessmentResult?.list![2];
    for (QuestionSection section in part!.questions!) {
      options.add(BGExamWidget(
          questionItem: section.question![0], mode: BGExamWidgetMode.Graded));
    }
    return Scrollbar(
        child: SingleChildScrollView(
            primary: true, child: Column(children: options)));
  }

  Widget _buildReadingResultReview(BuildContext context) {
    return Column(children: [
      Expanded(
          child: Container(
              width: double.infinity,
              decoration: BoxDecoration(
                  borderRadius: BorderRadius.circular(8),
                  border: Border.all(
                    color: Colors.grey.withOpacity(0.1),
                    width: 1,
                  ),
                  color: Get.isDarkMode
                      ? AppTheme.colors.darkTheme2
                      : Colors.white,
                  boxShadow: [
                    BoxShadow(
                      blurRadius: 6,
                      spreadRadius: 0.2,
                      color: Colors.black.withOpacity(0.1),
                    ),
                  ]),
              child: Scrollbar(
                  thumbVisibility: true,
                  thickness: 10,
                  controller: controller.scrollCrl,
                  child: SingleChildScrollView(
                      controller: controller.scrollCrl,
                      child: Padding(
                          padding: EdgeInsets.fromLTRB(10, 10, 20, 10),
                          child: HtmlWidget(controller.reviewHtmlStr,
                              customStylesBuilder: (element) {
                            if (element.className == 'left-d') {
                              return {
                                'width': '30%',
                                'display': 'inline-block',
                                'border-bottom': 'solid 1px'
                              };
                            }
                            if (element.className == 'left-s') {
                              return {'padding-left': '20px'};
                            }
                            if (element.localName == 'td') {
                              return {'padding-left': '10px'};
                            }
                            return null;
                          },
                              textStyle: TextStyle(
                                  color: blackTextColor, height: 1.4))))))),
      Padding(
          padding: EdgeInsets.only(top: 20),
          child: Row(
              mainAxisAlignment: MainAxisAlignment.spaceBetween,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                TapRegion(
                    onTapOutside: (_) => FocusScope.of(Get.context!)
                        .requestFocus(new FocusNode()),
                    child: Container(
                      width: MediaQuery.of(context).size.width-300,
                      child: Column(
                          crossAxisAlignment: CrossAxisAlignment.start,
                          children: [
                            Text('Message to Student',
                                style: TextStyle(
                                    fontSize: 18,
                                    color: blackTextColor,
                                    fontWeight: FontWeight.bold)),
                            Container(
                                color: whiteTextColor,
                                height: 90,
                                padding: EdgeInsets.only(top: 5),
                                child: TextField(
                                  maxLines: 10,
                                  keyboardType: TextInputType.text,
                                  textInputAction: TextInputAction.done,
                                  controller: controller.messageTextController,
                                  readOnly: controller.isCompleted,
                                  decoration: InputDecoration(
                                      border: OutlineInputBorder(
                                          borderSide: BorderSide(
                                              color: Color(0xFFCCCCCC)))),
                                )),
                            TextButton(
                              onPressed: () {
                                controller.nextPage();
                              },
                              child: Text('What more Error Analysis?',
                                  style: TextStyle(
                                      fontSize: 18,
                                      color: Get.isDarkMode
                                          ? Colors.blueGrey
                                          : Colors.blueAccent,
                                      fontWeight: FontWeight.bold)),
                            )
                          ]),
                    )),
                Visibility(
                    visible: GetPlatform.isWeb,
                    child: Container(
                        width: 150,
                        height: 50,
                        margin: EdgeInsets.only(top: 45),
                        decoration: BoxDecoration(
                            color: whiteTextColor,
                            border: Border.all(
                              width: 1,
                              color: Get.isDarkMode
                                  ? Colors.white54
                                  : Colors.green,
                            ),
                            boxShadow: [
                              BoxShadow(
                                blurRadius: 3,
                                spreadRadius: 0.2,
                                color: Colors.black.withOpacity(0.2),
                              ),
                            ]),
                        child: RawMaterialButton(
                            onPressed: () {
                              controller.downloadReport();
                            },
                            child: Row(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  Icon(Icons.file_download,
                                      color: Get.isDarkMode
                                          ? Colors.white54
                                          : Colors.green),
                                  Text('Download',
                                      style: TextStyle(
                                          fontSize: 18,
                                          color: Get.isDarkMode
                                              ? Colors.white54
                                              : Colors.green,
                                          fontWeight: FontWeight.bold))
                                ]))))
                // Download Button
              ]))
    ]);
  }

  Widget _buildReadingBehavior(BuildContext context) {
    // double padding = MediaQuery.of(context).size.width * 0.05;
    double padding = 10;
    List? answer =
        controller.assessmentResult!.list![0].questions![0].question![0].answer;
    String audioId = '';
    if (answer != null && answer.isNotEmpty) {
      audioId = answer[0];
    }

    return Row(crossAxisAlignment: CrossAxisAlignment.start, children: [
      Expanded(
          flex: 7,
          child: Container(
              child: Column(children: [
            Visibility(
                visible: audioId.isNotEmpty,
                child: Padding(
                    padding: EdgeInsets.only(bottom: 20),
                    child: SampleAudioPlayer(
                      name: 'audioPlayerEvaluation',
                      audioId: audioId,
                      audioUrl: '',
                    ))),
            Expanded(
                child: Container(
                    width: double.infinity,
                    margin: EdgeInsets.only(left: padding, right: padding),
                    decoration: BoxDecoration(
                        border: Border.all(
                          color: Color(0xffDEE2E6),
                          width: 1,
                        ),
                        borderRadius: BorderRadius.circular(5),
                        color: whiteTextColor),
                    child: Scrollbar(
                        child: SingleChildScrollView(
                            primary: true,
                            child: Padding(
                                padding: EdgeInsets.all(20),
                                child: Column(
                                    crossAxisAlignment:
                                        CrossAxisAlignment.start,
                                    children: _buildBehaviorArticleContent(
                                        context)))))))
          ]))),
      Expanded(
          flex: 4,
          child: Column(children: [
            Expanded(
                child: Container(
                    color: Get.isDarkMode ? Colors.white10 : Colors.white,
                    margin: EdgeInsets.only(bottom: 20),
                    child: Obx(() {
                      return Scrollbar(
                          child: SingleChildScrollView(
                              primary: true,
                              child: Column(
                                  children: controller.behaviorScoreList
                                      .map(_buildBehaviorGridTextWidget)
                                      .toList())));
                    }))),
            RichText(
                text: TextSpan(
                    text:
                        "What does the data inform you about the student’s reading behavior?",
                    style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold, color: (Get.isDarkMode ? Color(0xFF757575) : Color(0xff59A59A)), height: 1.5),
                    children: [
                  WidgetSpan(child: _buildAlertIconButton('partBehaviorInfo'))
                ])),
            SizedBox(height: 20)
          ]))
    ]);
  }

  Widget _buildRecordTypeItem(
      BuildContext context, QuestionItem item, String questionId) {
    List<Widget> options = [];
    options.add(SizedBox(height: 15));
    options.add(ExamUtil.buildHeadInfoWidget(item.head, context));
    options.add(SizedBox(height: 25));
    if (item.answer != null &&
        item.answer!.length > 0 &&
        item.answer![0].isNotEmpty) {
      options.add(SampleAudioPlayer(
        name: 'audioPlayerEvaluation',
        audioId: item.answer![0],
        audioUrl: '',
      ));
      options.add(SizedBox(height: 25));
    }

    List<Widget> bottomScoreOptions = [];
    bottomScoreOptions.add(Text('Score',
        style: TextStyle(
            color: blackTextColor, fontSize: 18, fontWeight: FontWeight.w700)));
    bottomScoreOptions.add(_buildAlertIconButton('partTwo'));
    RxInt score = 0.obs;
    score.value = int.parse(controller.partTwoScoreMap[questionId] ?? '-1');
    for (int i = 0; i < 4; i++) {
      bottomScoreOptions.add(Obx(() => Row(children: [
            Radio<int>(
                value: i,
                activeColor: Colors.blue,
                groupValue: score.value,
                onChanged: (value) {
                  if (controller.isCompleted) return;
                  score.value = i;
                  controller.partTwoScoreMap[questionId] = i.toString();
                  if (!controller.isNextEnable.value) {
                    bool isHave = true;
                    controller.partTwoScoreMap.forEach((key, value) {
                      if (value == '-1') isHave = false;
                    });
                    if (isHave) controller.isNextEnable.value = true;
                  }
                }),
            Text(i.toString(),
                style: TextStyle(
                    fontFamily: 'Noto Sans SC',
                    fontSize: 18,
                    height: 1.8,
                    color: i ==
                            int.parse(
                                controller.partTwoScoreMap[questionId] ?? '-1')
                        ? Colors.blue
                        : (Get.isDarkMode ? Color(0xFF757575) : Colors.black87),
                    fontWeight: FontWeight.w500)),
          ])));
    }

    options.add(Row(children: bottomScoreOptions));
    options.add(SizedBox(height: 30));

    options.add(Flex(
      mainAxisAlignment: MainAxisAlignment.spaceBetween,
      direction: Axis.horizontal,
      children: List.generate(
          (MediaQuery.of(Get.context!).size.width * 0.1).toInt(), (_) {
        return SizedBox(
          width: 4,
          height: 2,
          child:
              DecoratedBox(decoration: BoxDecoration(color: Color(0xFFCCCCCC))),
        );
      }),
    ));

    return Column(children: options);
  }

  Widget _buildGradeWidget(BuildContext context, int stepNum) {
    switch (stepNum) {
      case 0:
        return _buildPageOne(context);
      case 1:
        return _buildPageTwo(context);
      case 2:
        return _buildPageThree(context);
      case 3:
        return _buildReadingResultReview(context);
      case 4:
        return _buildReadingBehavior(context);
      default:
        return SizedBox();
    }
  }

  Widget _buildGridTextWidget(List rowList) {
    Color textColor = Get.isDarkMode ? Colors.black12 : Color(0xFF17A2B8);
    final Color totalColor =
        Get.isDarkMode ? Colors.black26 : Color(0xFFA7EAEA);
    final Color partColor = Get.isDarkMode ? Colors.black38 : Color(0xFFD7EEEE);
    final Color geryColor = Get.isDarkMode ? Colors.black45 : Color(0xFFE8E8E8);
    final Color whiteColor = Get.isDarkMode ? Colors.black54 : Colors.white;

    switch (rowList[2]) {
      case 1:
        textColor = totalColor;
        break;
      case 2:
        textColor = partColor;
        break;
      case 3:
        textColor = geryColor;
        break;
      case 4:
        textColor = whiteColor;
        break;
    }

    if (rowList[0] == 'Scorecard') {
      return Container(
        width: double.infinity,
        padding: EdgeInsets.fromLTRB(5, 8, 0, 8),
        margin: EdgeInsets.only(bottom: 3),
        color: textColor,
        child: Text(rowList[0],
            style: TextStyle(
                fontSize: 20,
                color: blackTextColor,
                fontWeight: rowList[3] ? FontWeight.bold : FontWeight.normal)),
      );
    }
    Widget widget = Text(rowList[1].toString(),
        textAlign: TextAlign.right,
        style: TextStyle(
            fontSize: 20, color: blackTextColor, fontWeight: FontWeight.bold));
    if (rowList[0] == 'Errors') {
      widget = TextButton(
        style: TextButton.styleFrom(
            minimumSize: Size.zero,
            padding: EdgeInsets.zero,
            tapTargetSize: MaterialTapTargetSize.shrinkWrap,
            alignment: Alignment.centerRight),
        onPressed: () {
          if (controller.isCompleted) return;
          controller.dealDataWithScoreList(true);
        },
        child: Text(rowList[1].toString(),
            style: TextStyle(
                fontSize: 20,
                color: Color(0xFF0B7FD2),
                fontWeight: FontWeight.bold)),
      );
    }

    if (rowList[0] == 'Update Accuracy Rate') {
      // rowList[1]为0，显示TextField；>0显示Text
      widget = TapRegion(
          onTapOutside: (_) =>
              FocusScope.of(Get.context!).requestFocus(new FocusNode()),
          child: Row(children: [
            Expanded(
                child: TextField(
              keyboardType: TextInputType.number,
              textAlign: TextAlign.center,
              textInputAction: TextInputAction.done,
              controller: controller.textController,
              onTapOutside: (value) {
                String value = controller.textController.text;
                if (value == '') {
                  controller.scoreList[14][1] = '';
                } else {
                  controller.scoreList[14][1] =
                      int.parse(value) > 100 ? '100' : value;
                }
              },
              onSubmitted: (value) {
                String value = controller.textController.text;
                if (value == '') {
                  controller.scoreList[14][1] = '';
                } else {
                  controller.scoreList[14][1] =
                      int.parse(value) > 100 ? '100' : value;
                }
              },
              inputFormatters: [
                FilteringTextInputFormatter.digitsOnly,
                LengthLimitingTextInputFormatter(3)
              ],
              decoration: InputDecoration(
                  border: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(10),
                      borderSide:
                          BorderSide(color: Color(0xFFCED4DA), width: 1))),
            )),
            const SizedBox(width: 2),
            SizedBox(
                width: 15,
                child: Text('%',
                    style: TextStyle(
                        fontWeight: FontWeight.bold,
                        fontSize: 20,
                        color: blackTextColor)))
          ]));
    }
    return Container(
        margin: EdgeInsets.only(bottom: 3),
        padding: EdgeInsets.zero,
        color: textColor,
        child: Row(children: [
          Expanded(
              flex: 5,
              child: Container(
                decoration: BoxDecoration(
                    border: Border(
                        right: BorderSide(
                  width: 3,
                  color: (rowList[0] == 'Update Accuracy Rate')
                      ? Colors.transparent
                      : (Get.isDarkMode ? Colors.white10 : Colors.white),
                ))),
                padding: EdgeInsets.fromLTRB(5, 8, 5, 8),
                child: Text(rowList[0],
                    textAlign: TextAlign.left,
                    style: TextStyle(
                        fontSize: 20,
                        color: blackTextColor,
                        fontWeight:
                            rowList[3] ? FontWeight.bold : FontWeight.normal)),
              )),
          Expanded(
              flex: 3,
              child: Container(
                  padding: EdgeInsets.fromLTRB(0, 8, 5, 8), child: widget))
        ]));
  }

  List<Widget> _buildArticleContent(BuildContext context) {
    List<Widget> columns = [];
    List<Widget> options = [];
    TextStyle textStyle = TextStyle(fontSize: 20, color: blackTextColor);
    const StrutStyle strutStyle =
        StrutStyle(forceStrutHeight: true, leading: 1.5);
    for (int i = 0; i < controller.articleList!.length; i++) {
      var item = controller.articleList![i];
      if (item.value == ' ') {
        options.add(Text(item.value!, style: textStyle));
      } else if (item.value == '\r\n') {
        columns.add(Wrap(children: options));
        options = [];
      } else {
        RxString selectStatus = item.status!.obs;
        if (options.length > 0) options.add(Text(' ', style: textStyle));
        RxString tips = ''.obs;
        if (StrUtil.hasValue(item.status)) {
          for (var status in controller.statusList) {
            if (item.status == status[1]) {
              tips.value = status[0];
              break;
            }
          }
        }
        options.add(Obx(() {
          return PopupMenuButton(
              tooltip: tips.value,
              offset: Offset(0, 32),
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(6.0),
                  side: BorderSide(color: Colors.black45)),
              elevation: 20,
              onSelected: (Object selectItem) {
                if (controller.isCompleted) return;
                String value = selectItem as String;
                item.status = value == item.status ? '' : value;
                selectStatus.value = item.status!;
                if (StrUtil.hasValue(item.status)) {
                  for (var status in controller.statusList) {
                    if (item.status == status[1]) {
                      tips.value = status[0];
                      break;
                    }
                  }
                } else {
                  tips.value = '';
                }
                controller.dealDataWithScoreList(false);
              },
              child: Text(item.value!,
                  strutStyle: strutStyle,
                  style: TextStyle(
                      fontSize: 20,
                      color: blackTextColor,
                      backgroundColor: selectStatus.value.isEmpty
                          ? Colors.transparent
                          : Colors.red.withAlpha(64))),
              itemBuilder: (BuildContext context) => controller.statusList
                  .map((status) => PopupMenuItem(
                      value: status[1],
                      height: 40,
                      child: Text(status[0],
                          style: TextStyle(
                              color: blackTextColor,
                              fontFamily: 'Montserrat',
                              letterSpacing: 0.1,
                              fontWeight: status[1] == selectStatus.value
                                  ? FontWeight.bold
                                  : FontWeight.normal))))
                  .toList());
        }));
      }
      if (i == controller.articleList!.length - 1 && item.value! != '\r\n') {
        columns.add(Wrap(children: options));
        options = [];
      }
    }

    return columns;
  }

  Widget _buildBehaviorGridTextWidget(List rowList) {
    Color textColor = Get.isDarkMode ? Colors.black12 : Color(0xFF17A2B8);
    final Color totalColor =
        Get.isDarkMode ? Colors.black26 : Color(0xFFA7EAEA);
    final Color partColor = Get.isDarkMode ? Colors.black38 : Color(0xFFD7EEEE);
    final Color geryColor = Get.isDarkMode ? Colors.black45 : Color(0xFFE8E8E8);
    final Color whiteColor = Get.isDarkMode ? Colors.black54 : Colors.white;

    switch (rowList[2]) {
      case 1:
        textColor = totalColor;
        break;
      case 2:
        textColor = partColor;
        break;
      case 3:
        textColor = geryColor;
        break;
      case 4:
        textColor = whiteColor;
        break;
    }

    if (rowList[0] == 'Scorecard') {
      return Container(
        width: double.infinity,
        padding: EdgeInsets.fromLTRB(5, 8, 0, 8),
        margin: EdgeInsets.only(bottom: 3),
        color: textColor,
        child: Text(rowList[0],
            style: TextStyle(
                fontSize: 20,
                color: blackTextColor,
                fontWeight: FontWeight.bold)),
      );
    }
    Widget leftWidget = Text(rowList[0],
        textAlign: TextAlign.left,
        style: TextStyle(
            fontSize: 20, color: blackTextColor, fontWeight: FontWeight.bold));

    Widget rightWidget = Text(rowList[1].toString(),
        textAlign: TextAlign.right,
        style: TextStyle(
            fontSize: 20, color: blackTextColor, fontWeight: FontWeight.bold));

    if (rowList[0] == 'MSVT') {
      leftWidget = Row(children: [
        Text(rowList[0],
            textAlign: TextAlign.left,
            style: TextStyle(
                fontSize: 20,
                color: blackTextColor,
                fontWeight: FontWeight.bold)),
        _buildAlertIconButton('partBehaviorCue')
      ]);

      rightWidget = TextButton(
        style: TextButton.styleFrom(
            minimumSize: Size.zero,
            padding: EdgeInsets.zero,
            tapTargetSize: MaterialTapTargetSize.shrinkWrap,
            alignment: Alignment.centerRight),
        onPressed: () {
          if (controller.isCompleted) return;
          controller.dealBehaviorDataWithScoreList(true);
        },
        child: Text(rowList[1].toString(),
            style: TextStyle(
                fontSize: 20,
                color: Color(0xFF0B7FD2),
                fontWeight: FontWeight.bold)),
      );
    }

    return Container(
        margin: EdgeInsets.only(bottom: 3),
        padding: EdgeInsets.zero,
        color: textColor,
        child: Row(children: [
          Expanded(
              flex: 5,
              child: Container(
                  decoration: BoxDecoration(
                      border: Border(
                          right: BorderSide(
                    width: 3,
                    color: Get.isDarkMode ? Colors.white10 : Colors.white,
                  ))),
                  padding: EdgeInsets.fromLTRB(5, 8, 5, 8),
                  child: leftWidget)),
          Expanded(
              flex: 3,
              child: Container(
                  padding: EdgeInsets.fromLTRB(0, 8, 5, 8), child: rightWidget))
        ]));
  }

  List<Widget> _buildBehaviorArticleContent(BuildContext context) {
    List<Widget> columns = [];
    List<Widget> options = [];
    TextStyle textStyle = TextStyle(fontSize: 20, color: blackTextColor);
    const StrutStyle strutStyle =
        StrutStyle(forceStrutHeight: true, leading: 1.5);
    for (int i = 0; i < controller.articleList!.length; i++) {
      var item = controller.articleList![i];
      if (item.value == ' ') {
        options.add(Text(item.value!, style: textStyle));
      } else if (item.value == '\r\n') {
        columns.add(Wrap(children: options));
        options = [];
      } else if (StrUtil.notHasValue(item.status)) {
        if (options.length > 0) options.add(Text(' ', style: textStyle));
        options.add(
            Text(item.value! + ' ', strutStyle: strutStyle, style: textStyle));
      } else {
        RxString selectStatus = item.behavior!.obs;
        if (options.length > 0) options.add(Text(' ', style: textStyle));

        List dataList = controller.behaviorErrorList;
        if (item.status == 'selfCorrection') {
          dataList = controller.behaviorSelfList;
        }

        if (item.status == 'incorrectIntonation') {
          dataList = controller.behaviorTList;
        }

        RxString tips = ''.obs;
        if (StrUtil.hasValue(item.behavior)) {
          for (var behavior in dataList) {
            if (item.behavior == behavior[1]) {
              tips.value = behavior[0];
              break;
            }
          }
        }
        /*
        if (controller.isCompleted) {
          options.add(Tooltip(
            message: tips,
            child: TextButton(
                onPressed: () {},
                child: Text(item.value!,
                    strutStyle: strutStyle,
                    style: TextStyle(
                        fontSize: 20,
                        color: Colors.black,
                        backgroundColor: item.status == 'incorrectIntonation'
                            ? Color(0xff62ecce)
                            : Colors.red.withAlpha(64)))),
          ));
        }
      */
        options.add(Obx(() {
          return PopupMenuButton(
              tooltip: tips.value,
              offset: Offset(0, 32),
              shape: RoundedRectangleBorder(
                  borderRadius: BorderRadius.circular(6.0),
                  side: BorderSide(color: Colors.black45)),
              elevation: 20,
              onSelected: (Object selectItem) {
                if (controller.isCompleted) return;
                String value = selectItem as String;
                item.behavior = value == item.behavior ? '' : value;
                selectStatus.value = item.behavior!;
                if (StrUtil.hasValue(item.behavior)) {
                  for (var behavior in dataList) {
                    if (item.behavior == behavior[1]) {
                      tips.value = behavior[0];
                      break;
                    }
                  }
                } else {
                  tips.value = '';
                }
                controller.dealBehaviorDataWithScoreList(false);
              },
              child: Text(item.value!,
                  strutStyle: strutStyle,
                  style: TextStyle(
                      fontSize: 20,
                      color: blackTextColor,
                      backgroundColor: item.status == 'incorrectIntonation'
                          ? Get.isDarkMode
                              ? Colors.blueGrey
                              : Color(0xff62ecce)
                          : Colors.red.withAlpha(64))),
              itemBuilder: (BuildContext context) => dataList
                  .map((status) => PopupMenuItem(
                      value: status[1],
                      height: 40,
                      child: Text(status[0],
                          style: TextStyle(
                              color: blackTextColor,
                              fontFamily: 'Montserrat',
                              letterSpacing: 0.1,
                              fontWeight: status[1] == selectStatus.value
                                  ? FontWeight.bold
                                  : FontWeight.normal))))
                  .toList());
        }));
      }
      if (i == controller.articleList!.length - 1 && item.value! != '\r\n') {
        columns.add(Wrap(children: options));
        options = [];
      }
    }

    return columns;
  }
}

Widget _buildAlertIconButton(String partType) {
  return Container(
    width: 32,
    height: 32,
    margin: EdgeInsets.only(left: 5),
    decoration: BoxDecoration(
        border: Border.all(
          color: Color(0xffDEE2E6),
          width: 1,
        ),
        borderRadius: BorderRadius.circular(16),
        color: Get.isDarkMode ? Colors.white54 : Color(0xFFFFB10D)),
    child: IconButton(
        iconSize: 24,
        padding: EdgeInsets.zero,
        onPressed: () {
          showGeneralDialog(
              context: Get.context!,
              transitionDuration: const Duration(milliseconds: 400),
              pageBuilder: (bc, ania, anis) {
                return _alertFluencyScoreInfoPage(partType);
              });
        },
        icon: Icon(Icons.question_mark,
            color: Get.isDarkMode ? Colors.black54 : Colors.white)),
  );
}

Widget _alertFluencyScoreInfoPage(String partType) {
  String showStr = '<div><h1>111</h1></div>';
  double height = 0;
  switch (partType) {
    case 'partOne':
      height = MediaQuery.of(Get.context!).size.height * 0.65;
      showStr =
          '<div> <h2 style="text-align: center;">Fluent</h2> <h3 style="text-align: center;">Level 4</h3> <h4>Reads primarily in larger, meaningful phrase groups. Although some regressions, repetitions, and deviations from text may be present, these do not appear to detract from the overall structure of the story. Preservation of the author’s syntax is consistent. Some or most of the story is read with expressive interpretation. Read all Chinese characters with correct corresponding tones, and the pace is consistent. </h4> <h3 style="text-align: center;">Level 3</h3> <h4>Reads primarily in three- or four-word phrase groups. Some small groupings may be present. However, the majority of phrasing seems appropriate and preserves the syntax of the author. Little or no expressive interpretation is present. Read most Chinese characters with correct corresponding tones, and the pace is somewhat inconsistent: sometimes faster and sometimes slower.</h4> <h2 style="text-align: center;">Non-fluent</h2> <h3 style="text-align: center;">Level 2</h3> <h4>Reads primarily in two-word phrases with some three- or four-word groupings. Some word-by-word reading may be present. Word groupings may seem awkward and unrelated to larger context of sentence or passage. Read some Chinese characters with correct corresponding tones, and the pace is somewhat slow.</h4> <h3 style="text-align: center;">Level 1</h3> <h4>Reads primarily word-by-word. Occasional two-word or three-word phrases may occur—but these are infrequent and/or they do not preserve meaningful syntax. Read most of Chinese characters with incorrect corresponding tones, and the pace is noticeably slow.</h4> <h3>&nbsp;</h3></div>';
      break;
    case 'partTwo':
      height = MediaQuery.of(Get.context!).size.height * 0.5;
      showStr =
          '<div> <div> <h3 style="text-align: center;">0</h3> <h4 style="text-align: center;">The response gives no evidence of text understand.</h4> </div> <div> <h3 style="text-align: center;">1</h3> <h4 style="text-align: center;">The response gives limited evidence of text understand. It includes doodles that are not interpretable.</h4> </div> <div> <h3 style="text-align: center;">2</h3> <h4 style="text-align: center;">The response gives some evidence of text understanding. It includes a person without doing an activity or only an activity/object was drawn.</h4> </div> <div> <h3 style="text-align: center;">3</h3> <h4 style="text-align: center;">The response gives sufficient evidence of text understanding. </h4> </div><h3>&nbsp;</h3> </div>';
      break;
    case 'partBehaviorCue':
      height = MediaQuery.of(Get.context!).size.height * 0.6;
      showStr =
          '<div class="modal-content"><div class="modal-header"><h3 class="modal-title" id="exampleModalLongTitle">Meaing Cue</h3></div><div class="modal-body"><h4>Does the student’s error make sense based on the&nbsp;meaning&nbsp;of the illustration or the text? For example, maybe the child read the word&nbsp;高兴&nbsp;instead of&nbsp;开心.</h4></div><div class="modal-header"><h3 class="modal-title" id="exampleModalLongTitle">Syntax Cue</h3></div><div class="modal-body"><h4>Does the student’s error follow grammatical rules and the&nbsp;sentence structure in the Chinese language? For example, maybe the child read&nbsp;看到&nbsp;instead of&nbsp;看见. In this case, the error may sound right.</h4></div><div class="modal-header"><h3 class="modal-title" id="exampleModalLongTitle">Visual Cue</h3></div><div class="modal-body"><h4>Is the student’s error visually similar to the word on the page or from memory? For example, the student may read&nbsp;人&nbsp;instead of&nbsp;入.</h4></div><div class="modal-header"><h3 class="modal-title" id="exampleModalLongTitle">Tonal Attempt</h3></div><div class="modal-body"><h4>the student could recognize the character, but the pinyin tone was incorrectly read.</h4></div><h3>&nbsp;</h3></div>';
      break;
    case 'partBehaviorInfo':
      height = MediaQuery.of(Get.context!).size.height * 0.65;
      showStr =
          '<div class="modal-content"><div class="modal-header"><h3 class="modal-title" id="exampleModalTitle">Meaing Cue</h3></div><div class="modal-body"><h4>Greater number on Meaning cues means a student’s ability to gather a book’s basic message by making meaning of it at the text, content, and word level. They think and evaluate what they read. They check whether the sentence “makes sense.” Meaning-appropriate errors (miscues) do not interrupt the general comprehension of the sentence or paragraph. A meaning miscue may be syntactically appropriate but may not have a letter-sound correlation.</h4></div><div class="modal-header"><h3 class="modal-title" id="exampleModalTitle">Syntax Cue</h3></div><div class="modal-body"><h4>Students who use structural cues are relying on their knowledge of the grammar and structure of the Chinese language to make the text sound right. Using this knowledge, students check whether or not the word or sentence sounds right.</h4></div><div class="modal-header"><h3 class="modal-title" id="exampleModalTitle">Visual Cue</h3></div><div class="modal-body"><h4>Students use their knowledge of the visual features of words and characters and then connect these features to their knowledge of the way words and letters sound when spoken.</h4></div><div class="modal-header"><h3 class="modal-title" id="exampleModalTitle">Tonal Attempt</h3></div><div class="modal-body"><h4>The student is confident in character recognition but misread the character with the incorrect tone. The misuse of tones does not interrupt the general comprehension of the sentence or paragraph. The student is encouraged to practice reading words and texts with correct tones to improve the naturality of the speaking skill.</h4></div><h3>&nbsp;</h3></div>';
      break;
  }
  return AlertDialog(
      shape: RoundedRectangleBorder(
        borderRadius: BorderRadius.circular(8),
      ),
      content: Container(
          width: MediaQuery.of(Get.context!).size.width * 0.6,
          height: height,
          child: Column(children: [
            SizedBox(
                height: height - 54,
                child: SingleChildScrollView(
                    child: HtmlWidget(
                  showStr,
                  textStyle: TextStyle(
                      color: Get.isDarkMode ? Colors.white54 : Colors.black,
                      height: 1.4),
                ))),
            const SizedBox(height: 5),
            ElevatedButton(
                style: ElevatedButton.styleFrom(
                    textStyle: TextStyle(
                        fontSize: 18,
                        fontFamily: 'Montserrat',
                        fontWeight: FontWeight.bold),
                    padding: EdgeInsets.symmetric(
                        horizontal: 32, vertical: GetPlatform.isWeb ? 20 : 12),
                    backgroundColor:
                        Get.isDarkMode ? Colors.white54 : Color(0xFF35A95D),
                    foregroundColor:
                        Get.isDarkMode ? Colors.black54 : Colors.white,
                    shape: RoundedRectangleBorder(
                      borderRadius: BorderRadius.circular(8),
                    )),
                onPressed: () {
                  Get.back();
                },
                child: Text('OK'))
          ])));
}

class PlaceSlideTransition extends AnimatedWidget {
  PlaceSlideTransition({
    Key? key,
    required Animation<Offset> position,
    this.transformHitTests = true,
    required this.child,
  }) : super(key: key, listenable: position);

  Animation<Offset>? get position => listenable as Animation<Offset>;
  late final bool transformHitTests;
  late final Widget child;

  @override
  Widget build(BuildContext context) {
    Offset offset = position!.value;
    if (position!.status == AnimationStatus.reverse) {
      offset = Offset(-offset.dx, offset.dy);
    }
    return FractionalTranslation(
        translation: offset,
        transformHitTests: transformHitTests,
        child: child);
  }
}
